#!/usr/bin/python
import os, sys, getopt
import fnmatch
import hashlib
from xml.etree import ElementTree
import subprocess
import time
import shutil

reload(sys)
sys.setdefaultencoding('utf8')

error_files = []

obs_src_host = os.environ.get("OBS_SRC_HOST", "100.109.84.199")
obs_meta_path = '/usr1/source_cache/obs_meta/projects'
euleros_data_path = '/usr1/tagmsg'
pulgins = ('tar_scm', 'tar_scm_kernel', 'tar_scm_repo', 'tar_scm_kernel_repo', 'tar_scm_repo_docker', 'tar_scm_kernels_repo')

def usage():
    print sys.argv[0] + " -l EulerOS:Update EulerOS:Custom"
    sys.exit(1)

def shell_cmd(s_cmd_line, inmsg=None):
    p = subprocess.Popen(s_cmd_line, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    if inmsg:
        p.stdin.write(inmsg)
    out, err = p.communicate()
    return p.returncode, out, err

def get_repocache_hash(scm, url, subdir, revision=None):
    """Calculate hash fingerprint for repository cache."""
    scm = scm.strip()
    url = url.strip()
    subdir = subdir.strip()
    if revision is not None:
        revision = revision.strip()

    digest = hashlib.new('sha256')
    digest.update(url)
    if scm == 'svn':
        digest.update('/' + subdir)
    if scm == 'git' and revision:
        digest.update('/' + revision)
    return digest.hexdigest()

def get_file_name(scm, url, subdir, revision):
    print("scm==={0}, url===={1}, subdir====={2}, revision===={3}".format(scm, url, subdir, revision))
    repodir = None
    if scm == 'repo':
        repohash = url
    else:
        if revision == None:
            repohash = get_repocache_hash(scm, url, subdir)
        else:
            repohash = get_repocache_hash(scm, url, subdir, revision)
    digest = hashlib.new('sha256')
    digest.update(repohash)
    return digest.hexdigest()

def get_repo_revison(file):
    with open(file,'rt') as f:
        return f.read()

def iterfindfiles(path, fnexp):
    for root, dirs, files in os.walk(path):
        for filename in fnmatch.filter(files, fnexp):
            yield os.path.join(root, filename)

def rsync_euleros_data(srcdir, desdir):
    if not os.path.exists(desdir):
        os.makedirs(desdir)
    cmd = 'expect ./DataGuard.exp %s %s %s' % (srcdir, desdir, obs_src_host)
    ret, out, err = shell_cmd(cmd)
    if ret != 0:
        print "run: %s : failed, the out is %s, the err is %s" % (cmd, out, err)
        return False
    else:
        print "rsync: %s success" % cmd
        return True

def project_deal(project_name):
    print 'start %s ...' % project_name
    cpath = os.path.join(obs_meta_path,project_name)
    print("project====={0}".format(project_name))
    sourcesfile = '{0}/.osc/_sources'.format(cpath)
    fout = open(sourcesfile,'w')
    for filename in iterfindfiles(cpath, "_service"):
        package_name = filename.split('/')[-2]
        with open(filename, 'rt') as f:
            msglist=[]
            tree = ElementTree.parse(f)
            root = tree.getroot()
            for child in root:
                if child.attrib['name'] not in pulgins:
                    continue
                subdir = ''
                scm = url = revision = None
                for child2 in child:
                    if child2.attrib['name'] == 'scm':
                        scm = child2.text.strip()
                    if child2.attrib['name'] == 'url':
                        url = child2.text.strip()
                    if child2.attrib['name'] == 'subdir':
                        subdir = child2.text
                        if subdir:
                            subdir = subdir.strip()
                    if child2.attrib['name'] == 'revision':
                        revision = child2.text
                        if revision:
                            revision = revision.strip()
                filename = get_file_name(scm, url, subdir, revision)
                dir = '/usr1/tagmsg/euleros-version'
                file = os.path.join(dir, filename)
                if not os.path.exists(file):
                    error_files.append('error obs info {0} {1} {2} {3}'.format(scm, url, subdir, revision))
                    print('error obs info {0} {1} {2} {3}'.format(scm, url, subdir, revision))
                    continue
                tagmsg = get_repo_revison(file)
                if scm == 'repo':
                    urlname, revision, tag = tagmsg.split(' ')
                else:
                    tag = tagmsg
                    urlname = url
                    if not revision:
                        revision = 'master'

                linemsg='<package name="{0}" scm="{1}" source="{2}" branch="{3}" tag="{4}" />\n'.format(package_name,scm,urlname,revision,tag)
                if linemsg not in msglist:
                    msglist.append(linemsg)
            fout.writelines(msglist)
    fout.close()

def main():
    if len(sys.argv) < 2:
        usage()
    try:
        options,args = getopt.getopt(sys.argv[1:],"l:",["list="])
    except getopt.GetoptError:
        sys.exit(1)
    project_list=[]
    for name,value in options:
        if name in ('-l', '--list'):
            for prj in value.split('@'):
                if prj not in project_list:
                    project_list.append(prj)

    rsync_euleros_data('/srv/cache/obs/tar_scm/repo/euleros-version', euleros_data_path)
    for project in project_list:
        project_deal(project)

if __name__ == '__main__':
    main()
    if len(error_files) > 1:
        print('error happened: {0}'.format(error_files))
        sys.exit(1)